home *** CD-ROM | disk | FTP | other *** search
- /*
- Choose.c
-
- Choose() uses the console to ask the user a multiple choice question and accept
- a typed answer. It minimizes the number of keystrokes the user has to type. The
- user can select the default answer by just hitting <cr>, or can select any of
- the choices by typing just enough characters (typically just one) to make an
- unambigious selection. Choose() automatically spells out the rest of the choice.
- The user DOES NOT have to terminate the answer with a return. This makes it
- feasible to ask the user a long series of multiple-choice questions, since the
- user can quickly hit return to obtain default answers and need only type one (or
- a few) characters to select non-default choices.
-
- int Choose(int defaultChoice,const char *query,const char *choices[],int n);
-
- choice=Choose(choice,"Will you eat %s?\n",breadFish,2);
-
- The first argument and returned value are int, with values in the range 0 to
- n-1, where n (the last argument) is the number of possible choices. The
- second argument is a format string to be used (without the optional trailing
- \n) in a printf statement. The optional %s will be expanded into a list of
- alternatives appropriately punctuated by commas and "or". The third argument is
- an array of n string pointers, one string per choice. If the second argument
- ends in \n then the printing of that newline character is delayed until AFTER printing
- the user's choice.
-
- The other routines in this file, MultipleChoice() and YesOrNo() are obsolete,
- since Choose() is more convenient, but they are retained for support of old
- programs that may use them. Choose is implemented by calling MultipleChoice.
-
- MultipleChoice() accepts (and echoes on the console) a partial typed response to
- a multiple-choice question, expanding the response to print the full answer that
- it uniquely specifies. If alternative answers begin with the same letters (e.g.
- "Arabic" and "Armenian") then MultipleChoice keeps accepting characters until an
- answer is uniquely determined. Typing any non-printing character (e.g. Return or
- Enter) terminates the typed string, e.g. to distinguish "ant" from "anteater".
- If the typed string doesn't match any of the supplied answer strings then
- MultipleChoice makes the defaultChoice. Thus the user can select the default
- answer by just hitting return.
-
- YesOrNo() restricts the answers to "Yes" and "No", with a Boolean argument
- specifying the default.
-
- EXAMPLE:
- static char bread[]="Bread",fish[]="Fish",fowl[]="Fowl";
- static char *breadFishFowl[]={bread,fish,fowl};
- short choice=1;
-
- // new way
- choice=Choose(choice,"Would you like to eat %s?\n",breadFishFowl,3);
- stillHungry=Choose(stillHungry,"Do you want dessert?\n",noYes,2);
-
- // old way
- printf("Would you like to eat Bread, Fish, or Fowl?");
- choice=MultipleChoice(choice,3,breadFishFowl);
- printf("\n");
-
- // old way
- printf("Do you want dessert?");
- choice=YesOrNo(choice);
- printf("\n");
-
- NOTE:
- The declarations above explicitly allocate space for the strings "Bread" and "Fish".
- In a stand-alone application you could implicitly allocate that space,
- char *breadFishFowl[]={"Bread","Fish","Fowl"};
- but the THINK C compiler doesn't allow this in code resources
- (e.g. a MATLAB MEX file).
-
- HISTORY:
- 2/16/93 dgp wrote YesOrNo().
- 5/24/93 dgp added MultipleChoice().
- 9/24/93 dgp cosmetic.
- 1/25/94 dgp enhanced MultipleChoice() to accept characters until they uniquely
- specify an answer, as suggested by Bart Farell.
- 7/9/94 dgp added Choose().
- 7/13/94 dgp renamed file "Choose.c".
- 8/1/94 dgp fixed bug in MultipleChoice(), I was backspacing one too many times.
- 9/21/94 dgp added fflush(stdin) to MultipleChoice(), which works better when
- there's no unbuffered input.
- 1/5/95 dgp updated to CW5, eliminating the cludges with SIOUXtextWindow.
- 6/18/95 dgp changed "abort" to "exit" for better compatibility with CW atexit().
- */
- #include "VideoToolbox.h"
- #if !defined(__TYPES__)
- typedef unsigned char Boolean;
- #endif
- #define free(ptr) DisposePtr((Ptr)(ptr))
- #define malloc(bytes) (void *)NewPtr(bytes)
- static char no[]="No",yes[]="Yes";
- char *noYes[]={no,yes};
-
- int Choose(int defaultChoice,const char *query,char *choices[],int n)
- {
- Boolean newline;
- int choice;
- static char *string=NULL;
- char *choiceList;
-
- newline=(query[strlen(query)-1]=='\n');
- choiceList=ChoiceStr(choices,n);
- string=malloc(strlen(query)+strlen(choiceList)+1);
- assert(string!=NULL);
- //return defaultChoice=1;
- sprintf(string,query,choiceList);
- if(newline)string[strlen(string)-1]=0; // strip the trailing newline; print it later.
- BreakLines(string,80);
- printf("%s",string);
- free(string);
- choice=MultipleChoice(defaultChoice,n,choices);
- if(newline)printf("\n");
- return choice;
- }
-
- Boolean YesOrNo(Boolean defaultChoice)
- /* Accept "y" or "n" and spell out "Yes" or "No". Anything else gets defaultChoice. */
- {
- return MultipleChoice(defaultChoice,2,noYes);
- }
-
- int MultipleChoice(short defaultChoice,short nChoices,char *choices[])
- {
- char c,s[64];
- short i,j,choice,match,matches,k;
-
- printf(" (%s):",choices[defaultChoice]);
- fflush(stdout);
- for(k=0;k<sizeof(s)-1;k++){
- matches=0;
- do{
- c=getcharUnbuffered();
- }while(c==EOF);
- if(c==14)exit(1); /* Crude test for command-period. */
- if(!isprint(c))c=0;
- s[k]=c;
- s[k+1]=0;
- for(i=0;i<nChoices;i++){
- match=1;
- for(j=0;j<=k;j++)match&=(tolower(s[j])==tolower(choices[i][j]));
- if(match){
- choice=i;
- matches++;
- }
- }
- if(matches<=1 || s[k]==0)break;
- printf("%c",c);
- fflush(stdout);
- }
- fflush(stdin); // get rid of any unused input
-
- /* Erase partial answer, which could be longer than the default answer. */
- /* -1 because we didn't print the last character typed by the user. */
- k=strlen(s)-1;
- for(j=0;j<k;j++)printf("\b \b");
-
- /* Print answer */
- if(matches==0)choice=defaultChoice;
- printf("%s.",choices[choice]);
- fflush(stdout);
- return choice;
- }
-
- char *ChoiceStr(char *choices[],int nChoices)
- {
- int i,size;
- static char *string=NULL;
-
- size=0;
- for(i=0;i<nChoices;i++)size+=strlen(choices[i])+6;
- string=realloc(string,size);
- assert(string!=NULL);
- string[0]=0;
- for(i=0;i<nChoices;i++){
- sprintf(string,"%s%s",string,choices[i]);
- if(i<nChoices-2)sprintf(string,"%s, ",string);
- if(i==nChoices-2){
- if(nChoices>2)sprintf(string,"%s, or ",string);
- else sprintf(string,"%s or ",string);
- }
- if(i==nChoices-1)sprintf(string,"%s",string);
- }
- return string;
- }
-